package com.rainbow.session

import cn.hutool.core.lang.Assert
import com.fasterxml.jackson.databind.ObjectMapper
import com.rainbow.emum.ResultEnum
import com.rainbow.util.ResultUtil
import org.slf4j.LoggerFactory
import org.springframework.http.HttpStatus
import org.springframework.security.web.DefaultRedirectStrategy
import org.springframework.security.web.RedirectStrategy
import org.springframework.security.web.util.UrlUtils
import org.springframework.util.StringUtils
import javax.servlet.http.HttpServletRequest
import javax.servlet.http.HttpServletResponse

/**
 *rainbow
 */
open class AbstractSessionStrategy {

    companion object {
        val logger = LoggerFactory.getLogger(AbstractSessionStrategy::class.java)
    }

    /**
     * 过期跳转的URL
     */
    var destinationUrl: String? = null

    /**
     * 重定向策略
     */
    var redirectStrategy: RedirectStrategy = DefaultRedirectStrategy()

    /**
     * 跳转前是否创建新的session
     */
    var createNewSession: Boolean = true

    private var objectMapper: ObjectMapper = ObjectMapper()


    constructor(invalidSessionUrl: String) {
        Assert.isTrue(UrlUtils.isValidRedirectUrl(invalidSessionUrl), "url must start with '/' or with 'http(s)'")
        Assert.isTrue(StringUtils.endsWithIgnoreCase(invalidSessionUrl, ".html"), "url must end with '.html'")
        this.destinationUrl = invalidSessionUrl
    }


    fun onSessionInvalid(request: HttpServletRequest, response: HttpServletResponse) {
        logger.info("session失效")
        if (createNewSession) {
            request.session
        }
        val sourceUrl = request.requestURL.toString()
        var targetUrl = ""
        if (StringUtils.endsWithIgnoreCase(sourceUrl, ".html")) {
            targetUrl = destinationUrl!!
            logger.info("跳转到${targetUrl}")
            redirectStrategy.sendRedirect(request, response, targetUrl)
        } else {
            val result = buildResponseContent(request)
            response.status = HttpStatus.UNAUTHORIZED.value()
            response.contentType = "application/json;charset=UTF-8"
            response.writer.write(objectMapper.writeValueAsString(result))
        }

    }

    fun buildResponseContent(request: HttpServletRequest): Any {
        var message = "session已失效"
        if (isConcurrency()) {
            message = "${message},有可能是并发登录导致的"
        }
        return ResultUtil.error(ResultEnum.SESSION_INVALID.code!!, message)
    }

    /**
     * session失效是否是并发导致的
     */
    open fun isConcurrency(): Boolean {
        return true
    }

}